package com.xjrsoft.module.oa.service.impl;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.config.ServerConfig;
import com.xjrsoft.common.utils.UploadUtil;
import com.xjrsoft.core.secure.utils.SecureUtil;
import com.xjrsoft.core.tool.node.ForestNodeMerger;
import com.xjrsoft.core.tool.utils.BeanUtil;
import com.xjrsoft.core.tool.utils.IoUtil;
import com.xjrsoft.module.base.entity.XjrBaseAnnexesFile;
import com.xjrsoft.module.base.service.IXjrBaseAnnexesFileService;
import com.xjrsoft.module.oa.dto.FileDto;
import com.xjrsoft.module.oa.dto.FilefolderDto;
import com.xjrsoft.module.oa.entity.XjrOaFilefolder;
import com.xjrsoft.module.oa.entity.XjrOaFileinfo;
import com.xjrsoft.module.oa.service.IXjrOaFilefolderService;
import com.xjrsoft.module.oa.service.IXjrOafileinfoService;
import com.xjrsoft.module.oa.service.IXjrOafilemanageService;
import com.xjrsoft.module.oa.utils.WpsUtil;
import com.xjrsoft.module.oa.vo.FilefolderVo;
import com.xjrsoft.module.oa.vo.FileinfoVo;
import com.xjrsoft.module.oa.vo.WpsFileVo;
import com.xjrsoft.module.upload.vo.UploadFileVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 文件表 服务实现类
 * </p>
 *
 * @author zwq
 * @since 2021-04-20
 */
@Service
@Scope("prototype")
public class XjrOafilemanageServiceImpl implements IXjrOafilemanageService {

    @Autowired
    private IXjrOaFilefolderService iXjrOaFilefolderService;

    @Autowired
    private IXjrOafileinfoService iXjrOafileinfoService;


    @Autowired
    private IXjrBaseAnnexesFileService iXjrBaseAnnexesFileService;


    @Autowired
    private IXjrBaseAnnexesFileService xjrBaseAnnexesFileService;

    /**
     * wps的appid
     */
    @Value("${xjrsoft.global-config.wps.app_id}")
    private String app_id;

    /**
     * wps的appsecret
     */
    @Value("${xjrsoft.global-config.wps.appsecret}")
    private String appsecret;

    @Value("${xjrsoft.global-config.wps.download_url}")
    public String download_url;


    @Value("${xjrsoft.global-config.oss.enabled}")
    private boolean enabled;

    @Autowired
    private ServerConfig serverConfig;

    @Override
    public List<Object> queryFileAndFolder(FileDto fileDto) throws Exception {


        String keywords = fileDto.getKeywords();
        Integer fileType = fileDto.getFileType();
        List<Object> retList = new ArrayList<>(10);
        List<XjrOaFileinfo> oaFileinfoList = new ArrayList<>();
        List<XjrOaFilefolder> oaFilefolderList = new ArrayList<>();
        if (fileType == null || fileType == 0) {
            //当keyword为空时为根目录
            if (!StringUtils.isEmpty(keywords)) {
                //查询所有
                oaFileinfoList = iXjrOafileinfoService.query(keywords, 0, 0);
                oaFilefolderList = iXjrOaFilefolderService.query(keywords, 0, 0);
            } else {
                //查询根目录文件或文件夹
                oaFileinfoList = iXjrOafileinfoService.query(keywords, 0, 1);
                oaFilefolderList = iXjrOaFilefolderService.query(keywords, 0, 1);
            }
        } else {
            //查找特定类型的文件
            oaFileinfoList = iXjrOafileinfoService.query(keywords, fileType, 0);
            oaFilefolderList = iXjrOaFilefolderService.query(keywords, fileType, 0);
        }
        if (oaFileinfoList != null && oaFileinfoList.size() > 0) {
            List<FileinfoVo> fileinfoVos = BeanUtil.copyList(oaFileinfoList, FileinfoVo.class);

            for (FileinfoVo fileinfoVo : fileinfoVos) {
                if (!enabled) {
                    //本地服务器
                    String filePath = fileinfoVo.getFilePath().replaceAll(File.separator + File.separator, "//");
                    String[] split = filePath.split("static");
                    if (split.length > 2) {
                        //获取到当前请求的host 用于套娃请求
                        fileinfoVo.setFilePath(serverConfig.getLocalUrl() + split[1]);
                    }
                }
            }

            retList.addAll(fileinfoVos);
        }
        if (oaFilefolderList != null && oaFilefolderList.size() > 0) {
            List<FilefolderVo> filefolderVos = BeanUtil.copyList(oaFilefolderList, FilefolderVo.class);
            retList.addAll(filefolderVos);
        }
        return retList;
    }


    /**
     * @author 湘北智造-框架开发组
     * @date:2019年12月16日
     * @description:保存文件信息到数据库
     */
    @Override
    public Map<String, Object> addFileInfo(UploadFileVo uploadFileVo, MultipartFile multfile, String folderId) throws Exception {
        if (uploadFileVo == null) {
            throw new Exception("文件保存失败");
        }
        // 保存文件信息
        XjrBaseAnnexesFile xjrBaseAnnexesFile = iXjrBaseAnnexesFileService.getById(uploadFileVo.getFileIdList().get(0));
        XjrOaFileinfo xjrOaFileinfo = new XjrOaFileinfo();
        xjrOaFileinfo.setFileId(xjrBaseAnnexesFile.getId());
        xjrOaFileinfo.setFileName(xjrBaseAnnexesFile.getFileName());
        xjrOaFileinfo.setFolderId(folderId == null ? "0" : folderId);
        xjrOaFileinfo.setDeleteMark(0);
        xjrOaFileinfo.setEnabledMark(1);

        //文件地址
        xjrOaFileinfo.setFilePath(xjrBaseAnnexesFile.getFilePath());
        xjrOaFileinfo.setFileSize(xjrBaseAnnexesFile.getFileSize());
        // 文件类型
        String ftype = xjrBaseAnnexesFile.getFileType();
        xjrOaFileinfo.setFileType(ftype);
        String fileType = "";
        // 文件类型:fileType: 1-文档 2-图片
        if (StringUtils.equals(ftype, "jpg") || StringUtils.equals(ftype, "png") || StringUtils.equals(ftype, "gif") || StringUtils.equals(ftype, "bmp")
                || StringUtils.equals(ftype, "svg")) {
            fileType = "2";
        } else {
            fileType = "1";
        }
        xjrOaFileinfo.setFileExtensions(fileType);
        Map<String, Object> result = new HashMap<>();
        boolean save = iXjrOafileinfoService.save(xjrOaFileinfo);
        if (save) {
                result.put("url", xjrOaFileinfo.getFilePath());
        }
        return result;
    }


    @Override
    public boolean logicDelete(String fileId) {
        if (!StringUtils.isEmpty(fileId)) {
            XjrOaFileinfo oaFileinfo = iXjrOafileinfoService.getById(fileId);
            XjrOaFilefolder oaFilefolder = iXjrOaFilefolderService.getById(fileId);
            if (oaFileinfo != null) {
                //删除文件
                oaFileinfo.setEnabledMark(0);
                return iXjrOafileinfoService.updateById(oaFileinfo);
            } else if (oaFilefolder != null) {
                //删除本文件夹
                oaFilefolder.setEnabledMark(0);
                boolean updateFolder = iXjrOaFilefolderService.updateById(oaFilefolder);
                //递归调用删除子文件夹及其子文件
                List<XjrOaFileinfo> sonFile = iXjrOafileinfoService.getSonFile(fileId, 1);
                Set<String> sonFileIds = sonFile.stream().map(XjrOaFileinfo::getFileId).collect(Collectors.toSet());
                List<XjrOaFilefolder> sonFolder = iXjrOaFilefolderService.getSonFolder(fileId, 1);
                Set<String> sonFolderIds = sonFolder.stream().map(XjrOaFilefolder::getId).collect(Collectors.toSet());
                sonFileIds.addAll(sonFolderIds);
                for (String sonFileId : sonFileIds) {
                    this.logicDelete(sonFileId);
                }
                return updateFolder;
            }
        }
        return false;
    }

    @Override
    public boolean delete(String fileId) {
        if (!StringUtils.isEmpty(fileId)) {
            XjrOaFileinfo oaFileinfo = iXjrOafileinfoService.getById(fileId);
            XjrOaFilefolder oaFilefolder = iXjrOaFilefolderService.getById(fileId);
            if (oaFileinfo != null) {
                //删除文件
                if (iXjrBaseAnnexesFileService.removeById(fileId) && iXjrOafileinfoService.removeById(fileId)) {
                    //删除本地或者oss上的文件
                    String filePath = oaFileinfo.getFilePath();
                    String projectPath = IoUtil.getProjectPath();
                    File file = FileUtil.file(projectPath + filePath);
                    if (file.exists()) {
                        return FileUtil.del(file);
                    } else {
                        return UploadUtil.delete(filePath);
                    }
                }
            } else if (oaFilefolder != null) {
                //删除本文件夹
                boolean updateFolder = iXjrOaFilefolderService.removeById(fileId);
                //递归调用删除子文件夹及其子文件
                List<XjrOaFileinfo> sonFile = iXjrOafileinfoService.getSonFile(fileId, 0);
                Set<String> sonFileIds = sonFile.stream().map(XjrOaFileinfo::getFileId).collect(Collectors.toSet());
                List<XjrOaFilefolder> sonFolder = iXjrOaFilefolderService.getSonFolder(fileId, 0);
                Set<String> sonFolderIds = sonFolder.stream().map(XjrOaFilefolder::getId).collect(Collectors.toSet());
                sonFileIds.addAll(sonFolderIds);
                for (String sonFileId : sonFileIds) {
                    this.delete(sonFileId);
                }
                return updateFolder;
            }
        }
        return false;
    }


    /**
     * @author 湘北智造-框架开发组
     * @date:2020年7月1日
     * @url: /reviewFile
     * @description:在线预览文件 operation:1-预览 	2-编辑
     */
    @Override
    public WpsFileVo reviewOrEditFile(String fileId, String operation) throws Exception {
        if (!("1".equals(operation) || "2".equals(operation))) {
            throw new Exception("参数错误!!!!");
        }
        XjrOaFileinfo xjrOaFileinfo = iXjrOafileinfoService.getById(fileId);
        String ftype = xjrOaFileinfo.getFileType();
        if (StringUtils.equals(ftype, "jpg") || StringUtils.equals(ftype, "png") || StringUtils.equals(ftype, "gif") || StringUtils.equals(ftype, "bmp")
                || StringUtils.equals(ftype, "svg")) {
            if ("2".equals(operation)) {
                throw new Exception("图片不能进行编辑!!!");
            }
            XjrBaseAnnexesFile xjrBaseAnnexesFile = xjrBaseAnnexesFileService.getById(fileId);
            if (xjrBaseAnnexesFile != null) {
                String filepath = download_url + "/annexes-files/" + fileId;
                WpsFileVo wpsFileVo = new WpsFileVo();
                wpsFileVo.setWpsUrl(filepath);
                return wpsFileVo;
            }
        }
        try {
            operation = "1".equals(operation) ? "read" : "write";
            String url = "https://wwo.wps.cn/office";

            if (xjrOaFileinfo != null) {
                String fileType = xjrOaFileinfo.getFileType();
                if (fileType == null || fileType.isEmpty()) {
                    return null;
                }
                if (fileType.endsWith("xls") || fileType.endsWith("xlsx")) {
                    url += "/s/";
                } else if (fileType.endsWith("ppt")) {
                    url += "/p/";
                } else if (fileType.endsWith("pdf")) {
                    url += "/f/";
                } else {
                    url += "/w/";
                }
                Map<String, String> paramMap = new HashMap<String, String>();
                paramMap.put("_w_appid", app_id);
                paramMap.put("_w_fname", fileId);
                paramMap.put("_w_fileId", fileId);
                paramMap.put("_w_userId", SecureUtil.getUserId());
                paramMap.put("_w_operation", operation);
                // 签名
                String signature = WpsUtil.getSignature(paramMap, appsecret);
                url += fileId + "?" + WpsUtil.getUrlParam(paramMap) + "&_w_signature=" + signature;
                WpsFileVo wpsFileVo = new WpsFileVo();
                wpsFileVo.setWpsUrl(url);
                return wpsFileVo;
            } else {
                throw new Exception("未找到该文件记录:");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("在线预览文件异常:" + e.toString());
        }
    }

    @Override
    public boolean shareFileOrFileFolder(String fileId) {
        if (!StringUtils.isEmpty(fileId)) {
            XjrOaFileinfo oaFileinfo = iXjrOafileinfoService.getById(fileId);
            XjrOaFilefolder oaFilefolder = iXjrOaFilefolderService.getById(fileId);
            if (oaFileinfo != null) {
                //共享文件
                oaFileinfo.setIsShare(1);
                return iXjrOafileinfoService.updateById(oaFileinfo);
            } else if (oaFilefolder != null) {
                //共享本文件夹
                oaFilefolder.setIsShare(1);
                boolean updateFolder = iXjrOaFilefolderService.updateById(oaFilefolder);
                //递归调用共享子文件夹及其子文件
                List<XjrOaFileinfo> sonFile = iXjrOafileinfoService.getSonFile(fileId, 1);
                Set<String> sonFileIds = sonFile.stream().map(XjrOaFileinfo::getFileId).collect(Collectors.toSet());
                List<XjrOaFilefolder> sonFolder = iXjrOaFilefolderService.getSonFolder(fileId, 1);
                Set<String> sonFolderIds = sonFolder.stream().map(XjrOaFilefolder::getId).collect(Collectors.toSet());
                sonFileIds.addAll(sonFolderIds);
                for (String sonFileId : sonFileIds) {
                    this.shareFileOrFileFolder(sonFileId);
                }
                return updateFolder;
            }
        }
        return false;
    }


    @Override
    public List<Object> getFolderInfoByParentId(String parentId) {
        XjrOaFilefolder oaFilefolder = iXjrOaFilefolderService.getById(parentId);
        ArrayList<Object> retList = new ArrayList<>();
        if (oaFilefolder != null) {
            List<XjrOaFileinfo> sonFile = iXjrOafileinfoService.getSonFile(parentId, oaFilefolder.getEnabledMark());
            List<XjrOaFilefolder> sonFolder = iXjrOaFilefolderService.getSonFolder(parentId, oaFilefolder.getEnabledMark());
            if (sonFolder != null && sonFolder.size() > 0) {
                List<FilefolderVo> filefolderVos = BeanUtil.copyList(sonFolder, FilefolderVo.class);
                retList.addAll(filefolderVos);
            }
            if (sonFile != null && sonFile.size() > 0) {
                List<FileinfoVo> fileInfoVos = BeanUtil.copyList(sonFile, FileinfoVo.class);

                for (FileinfoVo fileinfoVo : fileInfoVos) {
                    if (!enabled) {
                        String filePath = fileinfoVo.getFilePath().replaceAll(File.separator + File.separator, "//");
                        String[] split = filePath.split("static");
                        if (split.length > 2) {
                            fileinfoVo.setFilePath(split[1]);
                        }
                    }
                }

                retList.addAll(fileInfoVos);
            }
        }
        return retList;
    }

    @Override
    public boolean restoreFile(String fileId) {
        if (!StringUtils.isEmpty(fileId)) {
            XjrOaFileinfo oaFileinfo = iXjrOafileinfoService.getById(fileId);
            XjrOaFilefolder oaFilefolder = iXjrOaFilefolderService.getById(fileId);
            if (oaFileinfo != null) {
                //还原文件
                oaFileinfo.setEnabledMark(1);
                return iXjrOafileinfoService.updateById(oaFileinfo);
            } else if (oaFilefolder != null) {
                //还原本文件夹
                oaFilefolder.setEnabledMark(1);
                boolean updateFolder = iXjrOaFilefolderService.updateById(oaFilefolder);
                //递归调用还原子文件夹及其子文件
                List<XjrOaFileinfo> sonFile = iXjrOafileinfoService.getSonFile(fileId, 0);
                Set<String> sonFileIds = sonFile.stream().map(XjrOaFileinfo::getFileId).collect(Collectors.toSet());
                List<XjrOaFilefolder> sonFolder = iXjrOaFilefolderService.getSonFolder(fileId, 0);
                Set<String> sonFolderIds = sonFolder.stream().map(XjrOaFilefolder::getId).collect(Collectors.toSet());
                sonFileIds.addAll(sonFolderIds);
                for (String sonFileId : sonFileIds) {
                    this.restoreFile(sonFileId);
                }
                return updateFolder;
            }
        }
        return false;
    }

    @Override
    public boolean emptyTrash() {
        List<XjrOaFileinfo> xjrOaFileinfos = iXjrOafileinfoService.query(null, 3, 0);
        List<XjrOaFilefolder> xjrOaFilefolders = iXjrOaFilefolderService.query(null, 3, 0);
        TreeSet<String> ids = new TreeSet<>();
        if (xjrOaFileinfos != null && xjrOaFileinfos.size() > 0) {
            Set<String> fileinfosIds = xjrOaFileinfos.stream().map(XjrOaFileinfo::getFileId).collect(Collectors.toSet());
            ids.addAll(fileinfosIds);
        }
        if (xjrOaFilefolders != null && xjrOaFilefolders.size() > 0) {
            Set<String> filefolderIds = xjrOaFilefolders.stream().map(XjrOaFilefolder::getId).collect(Collectors.toSet());
            ids.addAll(filefolderIds);
        }
        for (String id : ids) {
            this.delete(id);
        }
        return true;
    }

    @Override
    public boolean addFolder(FilefolderDto filefolderDto) {
        XjrOaFilefolder xjrOaFilefolder = new XjrOaFilefolder();
        xjrOaFilefolder.setFolderName(filefolderDto.getFileName());
        String parentId = filefolderDto.getParentId();
        xjrOaFilefolder.setParentId(StringUtils.isEmpty(parentId) ? "0" : parentId);
        xjrOaFilefolder.setFolderType("文件夹");
        xjrOaFilefolder.setIsShare(0);
//        xjrOaFilefolder.setModifyDate(LocalDateTime.now());
        return iXjrOaFilefolderService.save(xjrOaFilefolder);
    }

    @Override
    public boolean updateFileName(String fileId, String fileName) throws Exception {
        if (fileName.isEmpty()) {
            throw new Exception("文件名不能为空!!!");
        }
        XjrOaFileinfo xjrOaFileinfo = iXjrOafileinfoService.getById(fileId);
        XjrOaFilefolder xjrOaFilefolder = iXjrOaFilefolderService.getById(fileId);
        if (xjrOaFilefolder != null) {
            xjrOaFilefolder.setFolderName(fileName);
            return iXjrOaFilefolderService.updateById(xjrOaFilefolder);
        }
        if (xjrOaFileinfo != null) {
            xjrOaFileinfo.setFileName(fileName);
            XjrBaseAnnexesFile xjrBaseAnnexesFile = iXjrBaseAnnexesFileService.getById(fileId);
            if (xjrBaseAnnexesFile != null) {
                xjrBaseAnnexesFile.setFileName(fileName);
                xjrBaseAnnexesFileService.updateById(xjrBaseAnnexesFile);
            }
            return iXjrOafileinfoService.updateById(xjrOaFileinfo);
        }
        return false;
    }

    @Override
    public boolean updateFile(String fileId, MultipartFile multfile) {
        //更新文件内容，先删后增
        XjrOaFileinfo oaFileinfo = iXjrOafileinfoService.getById(fileId);
        File uploadFile = IoUtil.toFile(multfile);
        File file = new File(IoUtil.getProjectPath() + oaFileinfo.getFilePath());
        boolean delete = file.delete();
        boolean add = uploadFile.renameTo(file);
        return delete && add;
    }

    @Override
    public List<FilefolderVo> getFileFolderTree() {
        //获取所有的文件夹
        List<XjrOaFilefolder> filefolderList = iXjrOaFilefolderService.list(Wrappers.<XjrOaFilefolder>query().lambda().eq(XjrOaFilefolder::getDeleteMark, 0).eq(XjrOaFilefolder::getEnabledMark, 1));
        List<FilefolderVo> filefolderVos = BeanUtil.copyList(filefolderList, FilefolderVo.class);
        return ForestNodeMerger.merge(filefolderVos);
    }

    //移动文件或文件夹
    @Override
    public boolean removeFile(String fileId, String folderId) {
        XjrOaFileinfo xjrOaFileinfo = iXjrOafileinfoService.getById(fileId);
        XjrOaFilefolder xjrOaFilefolder = iXjrOaFilefolderService.getById(fileId);
        if (xjrOaFilefolder != null) {
            xjrOaFilefolder.setParentId(folderId == null ? "0" : folderId);
            return iXjrOaFilefolderService.updateById(xjrOaFilefolder);
        }
        if (xjrOaFileinfo != null) {
            xjrOaFileinfo.setFolderId(folderId == null ? "0" : folderId);
            return iXjrOafileinfoService.updateById(xjrOaFileinfo);
        }
        return false;
    }
}